package com.yic.module.device.controller.admin.inspectionRecordInfo;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yic.framework.security.core.util.SecurityFrameworkUtils;
import com.yic.module.device.controller.admin.device.vo.DeviceExportReqVO;
import com.yic.module.device.controller.admin.inspectionDeviceEntry.vo.InspectionDeviceEntryExportReqVO;
import com.yic.module.device.controller.admin.inspectionPlan.vo.InspectionPlanExportReqVO;
import com.yic.module.device.controller.admin.inspectionRecord.vo.InspectionRecordCreateReqVO;
import com.yic.module.device.controller.admin.inspectionRecord.vo.InspectionRecordExportReqVO;
import com.yic.module.device.dal.dataobject.device.DeviceDO;
import com.yic.module.device.dal.dataobject.inspectionDeviceEntry.InspectionDeviceEntryDO;
import com.yic.module.device.dal.dataobject.inspectionPlan.InspectionPlanDO;
import com.yic.module.device.dal.dataobject.inspectionPlanEntry.InspectionPlanEntryDO;
import com.yic.module.device.dal.dataobject.inspectionRecord.InspectionRecordDO;
import com.yic.module.device.dal.dataobject.maintenancePlanEntry.MaintenancePlanEntryDO;
import com.yic.module.device.enums.inspectionPlanDevice.CommonStatusEnum;
import com.yic.module.device.enums.inspectionPlanDevice.DeviceInspectionPlanType;
import com.yic.module.device.enums.inspectionPlanDevice.EntryTypeEnum;
import com.yic.module.device.enums.inspectionPlanDevice.InspectionTypeEnum;
import com.yic.module.device.service.device.DeviceService;
import com.yic.module.device.service.inspectionDeviceEntry.InspectionDeviceEntryService;
import com.yic.module.device.service.inspectionPlan.InspectionPlanService;
import com.yic.module.device.service.inspectionPlanEntry.InspectionPlanEntryService;
import com.yic.module.device.service.inspectionRecord.InspectionRecordService;
import com.yic.module.device.service.maintenancePlanEntry.MaintenancePlanEntryService;
import com.yic.module.system.api.user.AdminUserApi;
import com.yic.module.system.api.user.dto.AdminUserRespDTO;
import net.bytebuddy.asm.Advice;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;

import com.yic.framework.common.pojo.PageResult;
import com.yic.framework.common.pojo.CommonResult;

import static com.yic.framework.common.pojo.CommonResult.success;

import com.yic.framework.excel.core.util.ExcelUtils;

import com.yic.framework.operatelog.core.annotations.OperateLog;

import static com.yic.framework.operatelog.core.enums.OperateTypeEnum.*;

import com.yic.module.device.controller.admin.inspectionRecordInfo.vo.*;
import com.yic.module.device.dal.dataobject.inspectionRecordInfo.InspectionRecordInfoDO;
import com.yic.module.device.convert.inspectionRecordInfo.InspectionRecordInfoConvert;
import com.yic.module.device.service.inspectionRecordInfo.InspectionRecordInfoService;

@Tag(name = "管理后台 - 巡检/点检记录明细")
@RestController
@RequestMapping("/device/inspection-record-info")
@Validated
public class InspectionRecordInfoController {

    @Resource
    private InspectionRecordInfoService inspectionRecordInfoService;
    @Resource
    private InspectionRecordService inspectionRecordService;
    @Resource
    private InspectionPlanEntryService inspectionPlanEntryService;
    @Resource
    private MaintenancePlanEntryService maintenancePlanEntryService;

    @Resource
    private InspectionDeviceEntryService inspectionDeviceEntryService;
    @Resource
    private InspectionPlanService inspectionPlanService;

    @Resource
    private DeviceService deviceService;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private TransactionTemplate transactionTemplate;

    @PostMapping("/create")
    @Operation(summary = "创建巡检/点检记录明细")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:create')")
    public CommonResult<Long> createInspectionRecordInfo(@Valid @RequestBody InspectionRecordInfoCreateReqVO createReqVO) {
        return success(inspectionRecordInfoService.createInspectionRecordInfo(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新巡检/点检记录明细")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:update')")
    public CommonResult<Boolean> updateInspectionRecordInfo(@Valid @RequestBody InspectionRecordInfoUpdateReqVO updateReqVO) {
        inspectionRecordInfoService.updateInspectionRecordInfo(updateReqVO);
        return success(true);
    }

    @PutMapping("/updateStatus")
    @Operation(summary = "更新检查记录状态")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:update')")
    public CommonResult<Boolean> updateStatus(@Valid @RequestBody InspectionRecordInfoUpdateReqVO updateReqVO) {
        inspectionRecordInfoService.updateStatus(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除巡检/点检记录明细")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:delete')")
    public CommonResult<Boolean> deleteInspectionRecordInfo(@RequestParam("id") Long id) {
        inspectionRecordInfoService.deleteInspectionRecordInfo(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得巡检/点检记录明细")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:query')")
    public CommonResult<InspectionRecordInfoRespVO> getInspectionRecordInfo(@RequestParam("id") Long id) {
        InspectionRecordInfoDO inspectionRecordInfo = inspectionRecordInfoService.getInspectionRecordInfo(id);
        return success(InspectionRecordInfoConvert.INSTANCE.convert(inspectionRecordInfo));
    }

    @GetMapping("/list")
    @Operation(summary = "获得巡检/点检记录明细列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:query')")
    public CommonResult<List<InspectionRecordInfoRespVO>> getInspectionRecordInfoList(@RequestParam("ids") Collection<Long> ids) {
        List<InspectionRecordInfoDO> list = inspectionRecordInfoService.getInspectionRecordInfoList(ids);
        return success(InspectionRecordInfoConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/page")
    @Operation(summary = "获得巡检/点检记录明细分页")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:query')")
    public CommonResult<PageResult<InspectionRecordInfoRespVO>> getInspectionRecordInfoPage(@Valid InspectionRecordInfoPageReqVO pageVO) {
        PageResult<InspectionRecordInfoDO> pageResult = inspectionRecordInfoService.getInspectionRecordInfoPage(pageVO);
        return success(InspectionRecordInfoConvert.INSTANCE.convertPage(pageResult));
    }

    @GetMapping("/pc-page")
    @Operation(summary = "获得巡检/点检异常记录明细分页")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:query')")
    public CommonResult<PageResult<InspectionRecordInfoRespVO>> getPcInspectionRecordInfoPage(@Valid InspectionRecordInfoPageReqVO pageVO) {
        pageVO.setStatus(EntryTypeEnum.ABNORMAL.getCode());
        List<String> planIdList = new ArrayList<>();
        if (StrUtil.isNotBlank(pageVO.getPlanName())) {
            InspectionPlanExportReqVO vo = new InspectionPlanExportReqVO();
            vo.setName(pageVO.getPlanName());
            List<InspectionPlanDO> inspectionPlanList = inspectionPlanService.getInspectionPlanList(vo);
            if (CollectionUtil.isNotEmpty(inspectionPlanList)) {
                planIdList = inspectionPlanList.stream().map(item-> item.getId()+"").collect(Collectors.toList());
            } else {
                planIdList.add("-1");
            }
        }
        pageVO.setPlanIdList(planIdList);
        List<String> deviceIdList = new ArrayList<>();
        if (StrUtil.isNotBlank(pageVO.getName())) {
            DeviceExportReqVO vo = new DeviceExportReqVO();
            vo.setName(pageVO.getName());
            List<DeviceDO> deviceDOList = deviceService.getList(vo);
            if (CollectionUtil.isNotEmpty(deviceDOList)) {
                deviceIdList = deviceDOList.stream().map(item-> item.getId()+"").collect(Collectors.toList());
            }
        }
        if (StrUtil.isNotBlank(pageVO.getCode())) {
            DeviceExportReqVO vo = new DeviceExportReqVO();
            vo.setCode(pageVO.getCode());
            List<DeviceDO> deviceDOList = deviceService.getList(vo);
            if (CollectionUtil.isNotEmpty(deviceIdList) && CollectionUtil.isNotEmpty(deviceDOList)) {
                List<String> deviceIdList2 = deviceDOList.stream().map(item-> item.getId()+"").collect(Collectors.toList());
                deviceIdList.retainAll(deviceIdList2);
            } else if (CollectionUtil.isEmpty(deviceIdList) && CollectionUtil.isNotEmpty(deviceDOList)) {
                deviceIdList = deviceDOList.stream().map(item-> item.getId()+"").collect(Collectors.toList());
            }
        }
        if ((StrUtil.isNotBlank(pageVO.getName()) || StrUtil.isNotBlank(pageVO.getCode())) && CollectionUtil.isEmpty(deviceIdList)) {
            deviceIdList.add("-1");
        }
        pageVO.setDeviceIdList(deviceIdList);
        PageResult<InspectionRecordInfoDO> pageResult = inspectionRecordInfoService.getPcInspectionRecordInfoPage(pageVO);
        PageResult<InspectionRecordInfoRespVO> result = InspectionRecordInfoConvert.INSTANCE.convertPage(pageResult);
        result.getList().forEach(item->{
            // 获取计划信息
            if (ObjectUtil.isNotNull(item.getPlanId())) {
                InspectionPlanDO inspectionPlan = inspectionPlanService.getInspectionPlan(item.getPlanId());
                item.setPlanName(inspectionPlan.getName());
            }
            // 获取计划记录信息
            if (ObjectUtil.isNotNull(item.getRecordId())) {
                InspectionRecordDO inspectionRecord = inspectionRecordService.getInspectionRecord(item.getRecordId());
                item.setInspectionType(inspectionRecord.getInspectionType());
            }
            // 获取设备信息
            if (ObjectUtil.isNotNull(item.getDeviceId())) {
                DeviceDO deviceDO = deviceService.get(item.getDeviceId());
                item.setName(deviceDO.getName());
                item.setCode(deviceDO.getCode());
            }
            // 封装检验人
            AdminUserRespDTO admin = adminUserApi.getUser(item.getUpdater());
            if (ObjectUtil.isNotEmpty(admin)) {
                item.setUserName(admin.getNickname());
            }
            // 设置图片列表
            String images = item.getImages();
            if (StrUtil.isNotBlank(images)) {
                if (images.contains("#")) {
                    String[] split = images.split("#");
                    List<String> list1 = new ArrayList<>(split.length);
                    Collections.addAll(list1, split);
                    item.setImagesList(list1);
                } else {
                    List<String> tmp = new ArrayList<>();
                    tmp.add(images);
                    item.setImagesList(tmp);
                }
            } else {
                item.setImagesList(new ArrayList<>());
            }
        });
        return success(result);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出巡检/点检记录明细 Excel")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:export')")
    @OperateLog(type = EXPORT)
    public void exportInspectionRecordInfoExcel(@Valid InspectionRecordInfoExportReqVO exportReqVO,
                                                HttpServletResponse response) throws IOException {
        List<InspectionRecordInfoDO> list = inspectionRecordInfoService.getInspectionRecordInfoList(exportReqVO);
        // 导出 Excel
        List<InspectionRecordInfoExcelVO> datas = InspectionRecordInfoConvert.INSTANCE.convertList02(list);
        ExcelUtils.write(response, "巡检/点检记录明细.xls", "数据", InspectionRecordInfoExcelVO.class, datas);
    }

    @GetMapping("/app-list")
    @Operation(summary = "获得移动端巡检/点检记录明细列表")
    @PreAuthorize("@ss.hasPermission('device:inspection-record-info:query')")
    public CommonResult<List<InspectionRecordInfoRespVO>> getAppInspectionRecordInfoList(InspectionRecordInfoExportReqVO exportReqVO) {
        // 点检类型数据处理
        if (StrUtil.isNotBlank(exportReqVO.getInspectionType())
                && exportReqVO.getInspectionType().equals(String.valueOf(InspectionTypeEnum.SPOT_CHECKS.getCode()))) {
            Long recordId = spotCheckDeal(exportReqVO);
            exportReqVO.setRecordId(recordId);
        }
        List<InspectionRecordInfoDO> list = inspectionRecordInfoService.getAppInspectionRecordInfoList(exportReqVO);
        List<InspectionRecordInfoRespVO> result = InspectionRecordInfoConvert.INSTANCE.convertList(list);
        result.forEach(item -> {
            if (ObjectUtil.isNotNull(exportReqVO.getRes()) && exportReqVO.getRes().equals(DeviceInspectionPlanType.MAINTENANCE_PLAN.getCode())) {
                // 获取保养项信息
                MaintenancePlanEntryDO entry = maintenancePlanEntryService.getMaintenancePlanEntry(item.getEntryId());
                if (ObjectUtil.isNotNull(entry)) {
                    item.setEntryId(entry.getId());
                    item.setMName(entry.getName());
                    item.setMType(entry.getType());
                    item.setMWorkHours(entry.getWorkHours());
                    item.setMContent(entry.getContent());
                    item.setMRemark(entry.getRemark());
                    item.setMManual(entry.getManual());
                }
            } else {
                // 获取检查项信息
                InspectionPlanEntryDO entry = inspectionPlanEntryService.getInspectionPlanEntry(item.getEntryId());
                if (ObjectUtil.isNotNull(entry)) {
                    item.setEntryId(entry.getId());
                    item.setName(entry.getName());
                    item.setCode(entry.getCode());
                    item.setDescription(entry.getContent());
                }
            }

            // 设置图片列表
            String images = item.getImages();
            if (StrUtil.isNotBlank(images)) {
                if (images.contains("#")) {
                    String[] split = images.split("#");
                    List<String> list1 = new ArrayList<>(split.length);
                    Collections.addAll(list1, split);
                    item.setImagesList(list1);
                } else {
                    List<String> tmp = new ArrayList<>();
                    tmp.add(images);
                    item.setImagesList(tmp);
                }
            } else {
                item.setImagesList(new ArrayList<>());
            }
        });
        return success(result);
    }

    public Long spotCheckDeal(InspectionRecordInfoExportReqVO exportReqVO) {
        Long recordId = -1L;
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        InspectionRecordExportReqVO reqVO = new InspectionRecordExportReqVO();
        reqVO.setInspectionType(InspectionTypeEnum.SPOT_CHECKS.getCode());
        reqVO.setDeviceId(exportReqVO.getDeviceId());
        reqVO.setCreator(loginUserId);
        reqVO.setCreateTime(exportReqVO.getCreateTime());
        List<InspectionRecordDO> inspectionRecordList = inspectionRecordService.getInspectionRecordList(reqVO);
        // 只有当天未生成过的，才能生成点检记录。其他日期只能查看
        if (CollectionUtil.isEmpty(inspectionRecordList) &&  LocalDate.now().equals(LocalDate.from(exportReqVO.getCreateTime()[0]))) {
            Long deviceId = exportReqVO.getDeviceId();
            // 初始化点检记录数据
            InspectionRecordCreateReqVO createReqVO = new InspectionRecordCreateReqVO();
            createReqVO.setCode(String.valueOf(new Date().getTime()));
            createReqVO.setInspectionType(InspectionTypeEnum.SPOT_CHECKS.getCode());
            createReqVO.setDeviceId(deviceId);
            Long inspectionRecordId = inspectionRecordService.createInspectionRecord(createReqVO);
            // 初始化点检记录明细数据
            InspectionDeviceEntryExportReqVO deviceEntryExportReqVO = new InspectionDeviceEntryExportReqVO();
            deviceEntryExportReqVO.setDeviceId(deviceId);
            List<InspectionDeviceEntryDO> inspectionDeviceEntryList = inspectionDeviceEntryService.getInspectionDeviceEntryList(deviceEntryExportReqVO);
            if (CollectionUtil.isNotEmpty(inspectionDeviceEntryList)) {
                List<Long> entryIdList = inspectionDeviceEntryList.stream().map(InspectionDeviceEntryDO::getEntryId).collect(Collectors.toList());
                List<InspectionPlanEntryDO> inspectionPlanEntryList = inspectionPlanEntryService.getInspectionPlanEntryList(entryIdList);
                List<Long> effectEntryIdList = inspectionPlanEntryList.stream()
                        .filter(entry -> entry.getStatus().equals(CommonStatusEnum.ENABLE.getCode()))
                        .map(InspectionPlanEntryDO::getId).collect(Collectors.toList());
                for (Long entryId : effectEntryIdList) {
                    InspectionRecordInfoCreateReqVO createReqVO1 = new InspectionRecordInfoCreateReqVO();
                    createReqVO1.setRecordId(inspectionRecordId);
                    createReqVO1.setDeviceId(deviceId);
                    createReqVO1.setEntryId(entryId);
                    inspectionRecordInfoService.createInspectionRecordInfo(createReqVO1);
                }
            }
            recordId = inspectionRecordId;
        } else if (CollectionUtil.isNotEmpty(inspectionRecordList)){
            recordId = inspectionRecordList.get(0).getId();
        }
        return recordId;
    }
}
